/*
 * CRaid.java
 *
 * Copyright (c) 2009 Giles Millward (Manigra). All rights reserved.
 *
 * This file is part of JRogueDPS.
 *
 * JRogueDPS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JRogueDPS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with JRogueDPS.  If not, see <http://www.gnu.org/licenses/>.
 */
package raidbuffs;

import geardatabase.CDatabase;
import geardatabase.CStats;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import paperdoll.CPaperDoll;
import utility.CUtility;

/**
 *
 * @author Mani
 */
public class CRaid {

    public enum RaidBuff {

        SUNDER_ARMOR, EXPOSE_ARMOR, MANGLE, TRAUMA, HOTC, MASTER_POISONER, TOTEM_OF_WRATH,
        SAVAGE_COMBAT, BLOOD_FRENZY, IMPROVED_FAERIE_FIRE, MISERY, FAERIE_FIRE, STING, COW,
        IMPROVED_SCORCH, WINTERS_CHILL, EBON_PLAGUEBRINGER, EARTH_AND_MOON, COE, HORN_OF_WINTER,
        STRENGTH_OF_EARTH, BOM, BATTLE_SHOUT, ABOMINATIONS_MIGHT, TRUESHOT_AURA, UNLEASHED_RAGE,
        FEROCIOUS_INSPIRATION, SANCTIFIED_RETRIBUTION, IMPROVED_MOONKIN_FORM, SWIFT_RETRIBUTION,
        BLOOD_PACT, COMMANDING_SHOUT, FORTITUDE, HEROIC_PRESENCE, LOTP, RAMPAGE, IMPROVED_ICY_TALONS,
        WINDFURY_TOTEM, MOONKIN_AURA, ELEMENTAL_OATH, MOTW, BOK, BLOODLUST,
        ELIXIR, FOOD_BUFF, SCROLL
    };
    HashMap<RaidBuff, CRaidItem> m_hashMap = new HashMap<RaidBuff, CRaidItem>();

    public CRaid() {
    }

    public void addElement(RaidBuff p_buff, JCheckBox p_checkBox) {
        m_hashMap.put(p_buff, new CRaidItem(p_checkBox, p_buff));
    }

    public void addElement(RaidBuff p_buff, JComboBox p_comboBox) {
        m_hashMap.put(p_buff, new CRaidItem(p_comboBox, p_buff));
    }

    public boolean getValue(RaidBuff p_buff) {
        return m_hashMap.get(p_buff).getValue();
    }

    public boolean getValue(RaidBuff p_buff, String p_subBuff) {
        return m_hashMap.get(p_buff).getValue(p_subBuff);
    }

    public CStats getStats(RaidBuff p_raidBuff) {
        return m_hashMap.get(p_raidBuff).getStats();
    }

    public CStats getTotalStats() {
        CStats l_totalStats = new CStats();
        for (RaidBuff l_key : m_hashMap.keySet()) {
            CRaidItem l_raidItem = m_hashMap.get(l_key);
            if (l_raidItem.getValue()) {
                l_totalStats.add(l_raidItem.getStats());
            }
        }

        return l_totalStats;
    }

    public void save() {
        String l_string = CUtility.openXMLFileSaveDialog("raidbuffs", "Set a filename for this raid buff set");
        if (l_string == null) {
            return;
        }

        this.save(l_string);
    }

    public void save(String p_fileName) {
        Document doc = DocumentFactory.getInstance().createDocument();
        Element root = doc.addElement("root");
        this.addXMLData(root);

        if (!p_fileName.endsWith(".xml")) {
            p_fileName = p_fileName + ".xml";
        }

        FileOutputStream fos;
        try {
            fos = new FileOutputStream(p_fileName);
            OutputFormat format = OutputFormat.createPrettyPrint();
            XMLWriter writer;
            try {
                writer = new XMLWriter(fos, format);
                try {
                    writer.write(doc);
                    writer.flush();
                    writer.close();
                } catch (IOException ex) {
                    Logger.getLogger(CRaid.class.getName()).log(Level.SEVERE, null, ex);
                }

            } catch (UnsupportedEncodingException ex) {
                Logger.getLogger(CRaid.class.getName()).log(Level.SEVERE, null, ex);
            }

        } catch (FileNotFoundException ex) {
            Logger.getLogger(CRaid.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void addXMLData(Element p_root) {
        Element l_buffs = p_root.addElement("raidbuffs");
        for (RaidBuff l_key : m_hashMap.keySet()) {
            CRaidItem l_raidItem = m_hashMap.get(l_key);
            if (l_key == RaidBuff.ELIXIR ||
                    l_key == RaidBuff.FOOD_BUFF ||
                    l_key == RaidBuff.SCROLL) {
                l_buffs.addAttribute(l_key.toString(), l_raidItem.m_comboBox.getSelectedItem().toString());
            } else {
                l_buffs.addAttribute(l_key.toString(), (l_raidItem.getValue() == true) ? "yes" : "no");
            }
        }
    }

    public void read() {
        String l_string = CUtility.openXMLFileOpenDialog("raidbuffs", "Choose a Raid Buff data file");
        if (l_string == null) {
            return;
        }

        this.read(l_string);
    }

    public void read(String l_fileName) {
        File l_xml = new File(l_fileName);
        SAXReader l_reader = new SAXReader();
        Document l_doc;
        try {
            l_doc = l_reader.read(l_xml);
            Element l_element = (Element) l_doc.selectSingleNode("//root/raidbuffs");
            this.parseXMLElement(l_element);
        } catch (DocumentException ex) {
            Logger.getLogger(CRaid.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void parseXMLElement(Element p_element) {
        String l_value = "";

        for (RaidBuff l_key : m_hashMap.keySet()) {
            CRaidItem l_raidItem = m_hashMap.get(l_key);
            l_value = p_element.attributeValue(l_key.toString());
            if (l_value != null)
            {
                if (l_key == RaidBuff.ELIXIR ||
                        l_key == RaidBuff.FOOD_BUFF ||
                        l_key == RaidBuff.SCROLL) {
                    l_raidItem.m_comboBox.setSelectedItem(l_value);
                } else {
                    if (l_value.equals("yes")) {
                        l_raidItem.m_checkBox.setSelected(true);
                    } else {
                        l_raidItem.m_checkBox.setSelected(false);
                    }
                }
            }
        }
    }


    // Hidden class for encapsulating GUI components in the
    // Raid buffs page
    private class CRaidItem {

        JCheckBox m_checkBox = null;
        JComboBox m_comboBox = null;
        CStats m_raidStat = null;
        RaidBuff m_buffType;

        CRaidItem(JCheckBox p_checkBox, RaidBuff p_buff) {
            m_checkBox = p_checkBox;
            m_buffType = p_buff;
            if (p_buff == RaidBuff.SUNDER_ARMOR) {
                // 3925 reduced armor
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.EXPOSE_ARMOR) {
                // 3925 reduced armor with 5 cb
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.MANGLE) {
                // 30% extra damage from bleed effects
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.TRAUMA) {
                // 30% extra damage from bleed effects
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.HOTC) {
                // 3% crit
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.MASTER_POISONER) {
                // 3% crit
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.TOTEM_OF_WRATH) {
                // 3% crit
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.SAVAGE_COMBAT) {
                // Physical dps up by 2%
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.BLOOD_FRENZY) {
                // Physical dps up by 2%
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.IMPROVED_FAERIE_FIRE) {
                // 3% spell hit
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.MISERY) {
                // 3% spell hit
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.FAERIE_FIRE) {
                // 1260 armor reduction
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.STING) {
                // 1260 armor reduction
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.COW) {
                // 1260 armor reduction
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.IMPROVED_SCORCH) {
                // 2% increase crit chance
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.WINTERS_CHILL) {
                // 2% increase crit chance
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.EBON_PLAGUEBRINGER) {
                // 13% magic damage
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.EARTH_AND_MOON) {
                // 13% magic damage
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.COE) {
                // 13% magic damage
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.HORN_OF_WINTER) {
                m_raidStat = new CStats("agility=155,strength=155");
            } else if (p_buff == RaidBuff.STRENGTH_OF_EARTH) {
                m_raidStat = new CStats("agility=178,strength=178");
            } else if (p_buff == RaidBuff.BOM) {
                m_raidStat = new CStats("attackPower=688");
            } else if (p_buff == RaidBuff.BATTLE_SHOUT) {
                m_raidStat = new CStats("attackPower=688");
            } else if (p_buff == RaidBuff.ABOMINATIONS_MIGHT) {
                // Increase attackpower by 10%
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.TRUESHOT_AURA) {
                // Increase attackpower by 10%
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.UNLEASHED_RAGE) {
                // Increase attackpower by 10%
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.FEROCIOUS_INSPIRATION) {
                // 3% increased dmg
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.SANCTIFIED_RETRIBUTION) {
                // 3% increased dmg
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.IMPROVED_MOONKIN_FORM) {
                // 3% haste
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.SWIFT_RETRIBUTION) {
                // 3% haste
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.BLOOD_PACT) {
                // increase health by 1330
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.COMMANDING_SHOUT) {
                // increase health by 2255
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.FORTITUDE) {
                // Stamina 165
                m_raidStat = new CStats("stamina=165");
            } else if (p_buff == RaidBuff.HEROIC_PRESENCE) {
                // 1% increase chance to hit
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.LOTP) {
                // 5% physical crit chance
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.RAMPAGE) {
                // 5% physical crit chance
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.IMPROVED_ICY_TALONS) {
                // 20% haste increase
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.WINDFURY_TOTEM) {
                // 20% haste increase
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.MOONKIN_AURA) {
                // 5% spell crit chance
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.ELEMENTAL_OATH) {
                // 5% spell crit chance
                m_raidStat = new CStats("");
            } else if (p_buff == RaidBuff.MOTW) {
                // Attributes increase by 51.8
                m_raidStat = new CStats("agility=52,strength=52,stamina=52");
            } else if (p_buff == RaidBuff.BOK) {
                // Total stats up by 10%
                m_raidStat = new CStats("");
            } else {
                // No static stats
                m_raidStat = new CStats();
            }
        }

        CRaidItem(JComboBox p_comboBox, RaidBuff p_buff) {
            m_comboBox = p_comboBox;
            m_buffType = p_buff;
        }

        public boolean getValue() {
            if (m_checkBox != null) {
                return m_checkBox.isSelected();
            }

            if (this.m_comboBox.getSelectedItem().toString().equals("None")) {
                return false;
            }

            return true;
        }

        public boolean getValue(String p_string) {
            return this.m_comboBox.getSelectedItem().toString().toLowerCase().equals(p_string.toLowerCase());
        }

        // Get static stats
        public CStats getStats() {
            if (m_checkBox != null) {
                return m_raidStat;
            }

            String l_current = this.m_comboBox.getSelectedItem().toString().toLowerCase();
            m_raidStat = new CStats();

            if (this.m_buffType == RaidBuff.ELIXIR) {
                if (l_current.equals("flask of endless rage")) {
                    m_raidStat.addAttackPower(180);
                } else if (l_current.equals("elixir of demonslaying")) {
                    m_raidStat.addAttackPower(265);
                } else if (l_current.equals("elixir of mighty agility")) {
                    m_raidStat.addAgility(45);
                } else if (l_current.equals("elixir of major agility")) {
                    m_raidStat.addAgility(30);
                    m_raidStat.addCritRating(12);
                }
            } else if (this.m_buffType == RaidBuff.FOOD_BUFF) {
                if (l_current.equals("agility food")) {
                    m_raidStat.addAgility(40);
                    m_raidStat.addStamina(40);
                } else if (l_current.equals("attack Power food")) {
                    m_raidStat.addAttackPower(80);
                    m_raidStat.addStamina(40);
                } else if (l_current.equals("armor Pen food")) {
                    m_raidStat.addArmorPenRating(40);
                    m_raidStat.addStamina(40);
                } else if (l_current.equals("crit food")) {
                    m_raidStat.addCritRating(40);
                    m_raidStat.addStamina(40);
                } else if (l_current.equals("expertise food")) {
                    m_raidStat.addExpertiseRating(40);
                    m_raidStat.addStamina(40);
                } else if (l_current.equals("haste food")) {
                    m_raidStat.addHasteRating(40);
                    m_raidStat.addStamina(40);
                } else if (l_current.equals("hit food")) {
                    m_raidStat.addHitRating(30);
                    m_raidStat.addStamina(40);
                }
            } else if (this.m_buffType == RaidBuff.SCROLL) {
                if (l_current.equals("agility vi")) {
                    m_raidStat.addAgility(20);
                } else if (l_current.equals("strength vi")) {
                    m_raidStat.addStrength(20);
                }
            }

            return m_raidStat;
        }
    }
}
